﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Reactive;
using System.Threading.Tasks;

namespace TfL
{
    public interface ITrackerNetFeed<T> : ISubject<T>, ITrackerNetFeedPoller<T>
    {
        string Ns { get; }
        string Url { get; set; }
        
    }

    /// <summary>
    /// base class for all tfl feeds
    /// implements <see cref="ITrackerNetFeedPoller{T}"/> and <see cref="ISubject{TSource,TResult}"/>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TrackerNetFeed<T> : ITrackerNetFeed<T>
    {
        public TrackerNetFeed(string url, string ns)
        {
            Url = url;
            Ns = ns;
        }
        
        public string Ns { get; private set; }

        public string Url { get; set; }

        #region IObserver<T> Members

        public void OnCompleted()
        {
            
            _subject.OnCompleted();
        }

        public void OnError(Exception error)
        {
            _subject.OnError(error);
        }

        public void OnNext(T value)
        {
            _subject.OnNext(value);
        }

        #endregion

        #region IObservable<T> Members

        public IDisposable Subscribe(IObserver<T> observer)
        {
            return _subject.Subscribe(observer);
        }

        #endregion

        public ISubject<T> Poll()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            var observable = Observable.FromAsyncPattern<System.Net.WebResponse>(request.BeginGetResponse, request.EndGetResponse);
            var respon = observable();
            respon.Subscribe(DecodeResponse);

            return this;
        }

        public ISubject<T> Poll(System.Threading.CancellationToken token, int period)
        {
            Task.Factory.StartNew(
                () =>
                    {
                        while (!token.IsCancellationRequested)
                        {
                            Poll();
                            token.WaitHandle.WaitOne(period);

                        }
                    },TaskCreationOptions.LongRunning);
            return this;
        }
        
        private readonly Subject<T> _subject = new Subject<T>();

        #region ITrackerNetFeed<T> Members


        public event Action<WebResponse> DecodeResponse = response=> { };

        #endregion
    }
}
